<template>
  <el-form
    ref="formRef"
    :model="modelValue"
    :rules="rules"
    :label-width="labelWidth"
    :inline="inline"
    :size="size"
  >
    <template v-for="field in fields" :key="field.prop">
      <!-- 根据字段类型渲染不同的表单项 -->
      <el-form-item
        :label="field.label"
        :prop="field.prop"
        :rules="field.rules"
      >
        <!-- 输入框 -->
        <el-input
          v-if="field.type === 'input'"
          v-model="modelValue[field.prop]"
          v-bind="field.props"
          :placeholder="field.placeholder || `请输入${field.label}`"
        >
          <template v-if="field.prefix" #prefix>
            <el-icon><component :is="field.prefix" /></el-icon>
          </template>
          <template v-if="field.suffix" #suffix>
            <el-icon><component :is="field.suffix" /></el-icon>
          </template>
        </el-input>

        <!-- 数字输入框 -->
        <el-input-number
          v-else-if="field.type === 'number'"
          v-model="modelValue[field.prop]"
          v-bind="field.props"
          :placeholder="field.placeholder || `请输入${field.label}`"
        />

        <!-- 选择器 -->
        <el-select
          v-else-if="field.type === 'select'"
          v-model="modelValue[field.prop]"
          v-bind="field.props"
          :placeholder="field.placeholder || `请选择${field.label}`"
        >
          <el-option
            v-for="option in field.options"
            :key="option.value"
            :label="option.label"
            :value="option.value"
          />
        </el-select>

        <!-- 日期选择器 -->
        <el-date-picker
          v-else-if="field.type === 'date'"
          v-model="modelValue[field.prop]"
          v-bind="field.props"
          :placeholder="field.placeholder || `请选择${field.label}`"
        />

        <!-- 时间选择器 -->
        <el-time-picker
          v-else-if="field.type === 'time'"
          v-model="modelValue[field.prop]"
          v-bind="field.props"
          :placeholder="field.placeholder || `请选择${field.label}`"
        />

        <!-- 开关 -->
        <el-switch
          v-else-if="field.type === 'switch'"
          v-model="modelValue[field.prop]"
          v-bind="field.props"
        />

        <!-- 单选框组 -->
        <el-radio-group
          v-else-if="field.type === 'radio'"
          v-model="modelValue[field.prop]"
          v-bind="field.props"
        >
          <el-radio
            v-for="option in field.options"
            :key="option.value"
            :label="option.value"
          >
            {{ option.label }}
          </el-radio>
        </el-radio-group>

        <!-- 复选框组 -->
        <el-checkbox-group
          v-else-if="field.type === 'checkbox'"
          v-model="modelValue[field.prop]"
          v-bind="field.props"
        >
          <el-checkbox
            v-for="option in field.options"
            :key="option.value"
            :label="option.value"
          >
            {{ option.label }}
          </el-checkbox>
        </el-checkbox-group>

        <!-- 级联选择器 -->
        <el-cascader
          v-else-if="field.type === 'cascader'"
          v-model="modelValue[field.prop]"
          :options="field.options"
          v-bind="field.props"
          :placeholder="field.placeholder || `请选择${field.label}`"
        />

        <!-- 文本域 -->
        <el-input
          v-else-if="field.type === 'textarea'"
          v-model="modelValue[field.prop]"
          type="textarea"
          v-bind="field.props"
          :placeholder="field.placeholder || `请输入${field.label}`"
        />

        <!-- 自定义插槽 -->
        <slot
          v-else-if="field.type === 'slot'"
          :name="field.prop"
          :field="field"
          :model="modelValue"
        />
      </el-form-item>
    </template>

    <!-- 表单按钮 -->
    <el-form-item v-if="showButtons">
      <slot name="buttons">
        <el-button type="primary" @click="handleSubmit">确定</el-button>
        <el-button @click="handleReset">重置</el-button>
      </slot>
    </el-form-item>
  </el-form>
</template>

<script setup lang="ts">
import { ref } from "vue";
import type { FormInstance, FormRules } from "element-plus";

type FieldType =
  | "input"
  | "select"
  | "radio"
  | "checkbox"
  | "switch"
  | "date"
  | "time"
  | "number"
  | "textarea"
  | "cascader"
  | "slot";

interface FormField {
  type: FieldType;
  label: string;
  prop: string;
  props?: Record<string, any>;
  options?: Array<{
    label: string;
    value: any;
  }>;
  prefix?: string;
  suffix?: string;
  placeholder?: string;
  rules?: FormRules;
}

interface Props {
  modelValue: Record<string, any>;
  fields: FormField[];
  rules?: FormRules;
  labelWidth?: string | number;
  labelPosition?: "left" | "right" | "top";
  size?: "large" | "default" | "small";
  inline?: boolean;
  disabled?: boolean;
  showButtons?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  labelWidth: "100px",
  inline: false,
  size: "default",
  showButtons: true,
});

const emit = defineEmits<{
  (e: "update:modelValue", value: Record<string, any>): void;
  (e: "submit", values: Record<string, any>): void;
  (e: "reset"): void;
}>();

// 表单实例
const formRef = ref<FormInstance>();

// 提交表单
const handleSubmit = async () => {
  if (!formRef.value) return;

  try {
    await formRef.value.validate();
    emit("submit", props.modelValue);
  } catch (error) {
    console.error("表单验证失败:", error);
  }
};

// 重置表单
const handleReset = () => {
  if (!formRef.value) return;
  formRef.value.resetFields();
  emit("reset");
};

// 暴露方法
defineExpose({
  formRef,
  validate: () => formRef.value?.validate(),
  resetFields: () => formRef.value?.resetFields(),
  clearValidate: (props?: string | string[]) =>
    formRef.value?.clearValidate(props),
});
</script>

<style lang="scss" scoped>
.el-form {
  // 内联表单项间距
  &.el-form--inline {
    .el-form-item {
      margin-right: 16px;
      margin-bottom: 16px;
    }
  }
}
</style>
